# -*- coding: utf-8 -*-
"""
中性策略框架 | 邢不行 | 2024分享会
author: 邢不行
微信: xbx6660
"""
import traceback
import os.path
import random
import pandas as pd
import warnings

warnings.filterwarnings('ignore')
pd.set_option('display.max_rows', 1000)
pd.set_option('expand_frame_repr', False)  # 当列太多时不换行
pd.set_option('display.unicode.ambiguous_as_wide', True)  # 设置命令行输出时的列对齐功能
pd.set_option('display.unicode.east_asian_width', True)
from datetime import datetime
from utils.commons import sleep_until_run_time, remedy_until_run_time, get_file_in_folder
from utils.dingding import send_wechat_work_msg
from utils.functions import create_finish_flag
from config import *


def exec_jobs(job_files, method='download', param=''):
    """
    执行所有job脚本中指定的函数
    :param job_files: 脚本名
    :param method: 方法名
    :param param: 方法参数
    """
    wrong_signal = 0
    # ===遍历job下所有脚本
    for job_file in job_files:
        # =加载脚本
        cls = __import__('data_job.%s' % job_file, fromlist=('',))
        # =执行download方法，下载数据
        try:
            if param:  # 指定有参数的方法
                getattr(cls, method)(param)
            else:  # 指定没有参数的方法
                getattr(cls, method)()
        except KeyboardInterrupt:
            print('退出')
            exit()
        except BaseException as e:
            msg = f'{job_file}  {method} 任务执行错误：' + str(e)
            print(msg)
            print(traceback.format_exc())
            send_wechat_work_msg(msg, error_webhook_url)
            wrong_signal += 1
        print('-' * 20, '分割线', '-' * 20)

    return wrong_signal


def run():
    while True:
        # =====sleep直到该小时开始。但是会随机提前几分钟。
        if not is_debug:  # 非调试模式，需要正常进行sleep
            random_time = random.randint(1 * 60, 2 * 60)  # 不建议使用负数。小时级别提前时间可以设置短一点
            run_time = sleep_until_run_time('5m', if_sleep=True, cheat_seconds=random_time)  # 每小时运行
        else:  # 调试模式，不进行sleep，直接继续往后运行
            # run_time = sleep_until_run_time('1h', if_sleep=False, cheat_seconds=0)  # 每小时运行
            # 以下代码可以测试的时候使用(UTC0点 日K才走完，国内时间对应是 早上8点)
            # run_time = datetime.strptime('2023-12-22 17:00:00', "%Y-%m-%d %H:%M:%S")
            # 测试当前小时的代码
            run_time = datetime.now().replace(minute=0, second=0, microsecond=0)

        # =====执行job目录下所有脚本
        # ===获取job目录下所有任务脚本
        job_files = get_file_in_folder(
            os.path.join(root_path, 'data_job'), file_type='.py', filters=['__init__', 'template'], drop_type=True
        )
        # ===执行所有job脚本中的 download 方法
        signal = exec_jobs(job_files, method='download', param=run_time)

        # =====定期清理文件中重复数据(目前的配置是：周日0点清理重复的数据)
        if run_time.isoweekday() == 7 and run_time.hour == 0 and run_time.minute == 0:  # 1-7表示周一到周日，0-23表示0-23点
            # ===执行所有job脚本中的 clean_data 方法
            exec_jobs(job_files, method='clean_data')

        # =====生成指数完成标识文件。如果标记文件过多，会删除7天之前的数据
        create_finish_flag(flag_path, run_time, signal)

        # =====清理数据
        del job_files

        # 本次循环结束
        print('-' * 20, '本次循环结束，%f秒后进入下一次循环' % 20, '-' * 20)
        print('\n')
        time.sleep(20)

        # =====补偿当前时间与run_time之间的差值
        remedy_until_run_time(run_time)


if __name__ == '__main__':
    while True:
        try:
            run()
        except Exception as err:
            msg = '数据中心出错，10s之后重新运行，出错原因: ' + str(err)
            print(msg)
            print(traceback.format_exc())
            send_wechat_work_msg(msg, error_webhook_url)
            time.sleep(10)
